package com.skivingcloud.file.service.impl;

import com.skivingcloud.admin.sys.entity.User;
import com.skivingcloud.common.utils.PageUtils;
import com.skivingcloud.common.utils.StringUtils;
import com.skivingcloud.common.utils.UuidUtil;
import com.skivingcloud.file.entity.SysFile;
import com.skivingcloud.file.mapper.SysFileMapper;
import com.skivingcloud.file.service.ISysFileService;
import com.skivingcloud.file.store.FileStorageDao;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;

import java.io.InputStream;
import java.io.OutputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import net.sf.json.JSONObject;

/**
 * <p>
 * 附件 服务实现类
 * </p>
 *
 * @author skivingcloud
 * @since 2022-03-02
 */
@Service
public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> implements ISysFileService {

	/**
	 * 文件存储的实现类集合，会根据fileStore来决定最终使用哪个实现类，所以实现类bean命名必须遵循fileStore+"FileStorageDao"的原则(bean名称，非类名)
	 */
	@Autowired
	private Map<String, FileStorageDao> map;

	/**
	 * 文件存储方案，fs:本地文件系统、hdfs:hdfs存储、filenet:filenet存储，其他方案请自行扩展。配置在application.properties中
	 */
	@Value("${skivingcloud.file.store:fs}")
	private String fileStore;

	/**
	 * 分页查询
	 * 
	 * @param params
	 * @return
	 */
	@Override
	public PageUtils queryPage(Map<String, Object> params) {
		PageUtils pageUtils = PageUtils.getPageInfo(params);
		Page<Object> p = PageHelper.startPage(pageUtils.getPage(), pageUtils.getLimit());
		SysFile fileManagement = (SysFile) JSONObject
				.toBean(JSONObject.fromObject(params.get("dataForm")), SysFile.class);
		Map<String, Object> queryParams = new HashMap<String, Object>();
		if (fileManagement != null) {
			if (StringUtils.isNotBlank(fileManagement.getFileName())) {
				queryParams.put("fileName", "%" + fileManagement.getFileName() + "%");
			}
		}
		List<Map<String, Object>> list = this.baseMapper.selectByPram(queryParams);
		pageUtils = new PageUtils(p);
		return pageUtils;
	}

	/**
	 * 保存文件
	 * 
	 * @param files      文件
	 * @param businessId 业务ID
	 * @param user       操作用户
	 * @return 文件ID集合
	 * @throws Exception
	 */
	@Override
    @Transactional(rollbackFor = Exception.class)
	public List<String> saveFiles(List<MultipartFile> files, String businessId, User user) throws Exception {
		List<String> ids = new ArrayList<String>();
		LocalDateTime date = LocalDateTime.now();
		for (MultipartFile file : files) {
			// 文件名
			String fileName = file.getOriginalFilename();
			// 后缀
			String extension = FilenameUtils.getExtension(fileName);
			// 字节数
			long fileSize = file.getSize();
			InputStream fileInputStream = file.getInputStream();
			SysFile fileManagement = new SysFile();
			// fileManagement.setBelongModule(belongModule);
			// fileManagement.setBelongModulePart(belongModulePart);
			fileManagement.setBusinessId(businessId);
			fileManagement.setCreater(user.getId());
			fileManagement.setCreateTime(date);
			fileManagement.setFileName(fileName);
			// fileManagement.setFilePath(filePath);
			fileManagement.setFileSize(((float) fileSize) / 1024);// 转成KB
			fileManagement.setFileState("1");
			fileManagement.setFileType(extension);
			// fileManagement.setGuid(guid);
			// fileManagement.setHdfsPath(hdfsPath);
			fileManagement.setId(UuidUtil.get32UUID());
			// fileManagement.setMemo(memo);
			fileManagement.setUpdater(user.getId());
			fileManagement.setUpdateTime(date);
			fileManagement.setVersion(0 + "");
			FileStorageDao fileStorageDao = map.get(fileStore + "FileStorageDao");
			fileStorageDao.saveFile(fileManagement, fileInputStream);
			this.baseMapper.insert(fileManagement);
			ids.add(fileManagement.getId());
		}
		System.out.println("上传文件的方法");
		return ids;
	}

	/**
	 * 根据id查询文件记录
	 * 
	 * @param id
	 * @return
	 */
	@Override
	public SysFile selectById(String id) {
		return this.baseMapper.selectById(id);
	}

	/**
	 * 下载文件
	 * 
	 * @param fileManagement
	 * @param response
	 * @throws Exception
	 */
	@Override
	public void downloadFile(SysFile fileManagement, HttpServletResponse response) throws Exception {
		response.setContentType("application/octet-stream;charset=UTF-8");
		response.setHeader("Content-Disposition",
				"attachment;filename=" + java.net.URLEncoder.encode(fileManagement.getFileName(), "UTF-8"));//
		response.addHeader("Pargam", "no-cache");
		response.addHeader("Cache-Control", "no-cache");
		OutputStream os = response.getOutputStream();
		FileStorageDao fileStorageDao = map.get(fileStore + "FileStorageDao");
		InputStream fileInputStream = fileStorageDao.getFile(fileManagement);
		byte[] buffer = new byte[fileInputStream.available()];
		fileInputStream.read(buffer);
		os.write(buffer);
		fileInputStream.close();
	}

	/**
	 * 返回文件字节
	 * 
	 * @param fileManagement
	 * @return
	 * @throws Exception
	 */
	@Override
	public byte[] getByte(SysFile fileManagement) throws Exception {
		FileStorageDao fileStorageDao = map.get(fileStore + "FileStorageDao");
		InputStream fileInputStream = fileStorageDao.getFile(fileManagement);
		byte[] buffer = new byte[fileInputStream.available()];
		fileInputStream.read(buffer);
		return buffer;
	}

	/**
	 * 将文件移动至“已删除”目录
	 * 
	 * @param asList
	 * @param userid
	 * @param fileState
	 * @throws Exception
	 */
	@Override
	public void moveFilePath(List<String> asList, String userid, String fileState) throws Exception {
		QueryWrapper<SysFile> queryWrapper = new QueryWrapper<SysFile>();
		queryWrapper.in("id", asList);
		List<SysFile> fileManagementList = this.baseMapper.selectList(queryWrapper);
		for (SysFile fileManagement : fileManagementList) {
			if (!"3".equals(fileManagement.getFileState())) {
				fileManagement.setFileState(fileState);// 把文件移到待删除文件夹,
				fileManagement.setUpdateTime(LocalDateTime.now());
				fileManagement.setUpdater(userid);
				FileStorageDao fileStorageDao = map.get(fileStore + "FileStorageDao");
				fileStorageDao.moveFilePath(fileManagement, fileState);
				this.baseMapper.updateById(fileManagement);
			}
		}

	}

	/**
	 * 根据业务id查询附件信息
	 * 
	 * @param businessId
	 * @return
	 */
	@Override
	public List<SysFile> getFileListByBusId(String businessId) {
		QueryWrapper<SysFile> queryWrapper = new QueryWrapper<SysFile>();
		queryWrapper.eq("file_state", "1");
		queryWrapper.eq("business_id", businessId);
		queryWrapper.orderByDesc("create_time");
		List<SysFile> fileManagementList = this.baseMapper.selectList(queryWrapper);
		return fileManagementList;
	}

	/**
	 * 根据业务id查询附件数量
	 * 
	 * @param busIds
	 * @return
	 */
	@Override
	public Map<String, Object> getFileCountByBusId(String[] busIds) {
		List<String> ids = Arrays.asList(busIds);
		return this.baseMapper.getFileCountByBusId(ids);
	}

}
